package org.moore.model;

import org.moore.utils.Data;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

// 地图模型类
public class Map {
    // 定义地图行数
    private static int rows;
    // 定义地图列数
    private static int cols;
    // 定义地图关卡等级
    private static int level;
    // 定义地图二维数组
    private static Block[][] map;
    // 定义游戏模式
    private static int mapType;
    // 定义心形形状
    private static final int[][] heartShape = {
            {0, 0, 1, 0, 0, 0, 1, 0, 0},
            {0, 1, 1, 1, 0, 1, 1, 1, 0},
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {0, 1, 1, 1, 1, 1, 1, 1, 0},
            {0, 0, 1, 1, 1, 1, 1, 0, 0},
            {0, 0, 0, 1, 1, 1, 0, 0, 0},
            {0, 0, 0, 0, 1, 0, 0, 0, 0}
    };
    // 定义最大可消除物数量
    private static int maxBlockType = 0;
    // 定义用于保存的数组
    private static int[][] saveMap;

    public Map(int rows, int cols, int level) {
        Map.rows = rows;
        Map.cols = cols;
        Map.level = level;
        map = new Block[rows][cols];
        saveMap = new int[rows][cols];
        // 根据不同等级关卡，运行不同地图生成方法
        switch (level) {
            case 1:
                generateSquareMap();
                break;
            case 2:
                generateLozengeMap();
                break;
            case 3:
                generateHeartShapedMap();
                break;
        }
    }

    public static List<Integer> setBlockTypes() {
        List<Integer> blockTypes = new ArrayList<>();
        // 根据不同等级关卡，设置不同类型数量的方块
        switch (level) {
            case 1:
                maxBlockType = 4;
                break;
            case 2:
                maxBlockType = 5;
                break;
            case 3:
                maxBlockType = 6;
                break;
        }
        for (int i = 1; i <= maxBlockType; i++){
            blockTypes.add(i);
        }
        return blockTypes;
    }

    public static List<Integer> blockTypes() {
        List<Integer> blockTypes = new ArrayList<>();
        for (int i = 1; i <= maxBlockType; i++){
            blockTypes.add(i);
        }
        return blockTypes;
    }

    // 加载对应类型图片
    public static Image loadImage(int blockType) {
        return new ImageIcon("Image/IMG " + blockType + ".png").getImage();
    }

    // 初始化矩形地图
    public static void generateSquareMap() {

        List<Integer> blockTypes;
        // 获取消除物类型集合
        if (Data.CUSTOM == 1) {
            blockTypes = blockTypes();
        } else {
            blockTypes = setBlockTypes();
        }
        // 将集合内的数据打乱
        Collections.shuffle(blockTypes, new Random());
        // 新建随机数
        Random random = new Random();
        // 开始循环遍历
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[0].length; j++) {
                // 定义随机数
                int randomNum;
                // 定义消除物类型
                int blockType;
                // 定义消除物图片
                Image blockImage;
                // 定义向上元素是否相同
                boolean aboveHasSameType;
                // 定义向左元素是否相同
                boolean leftHasSameType;
                // do...while循环（先运行再判断进入循环）
                do {
                    // 在类型范围进行随机数
                    randomNum = random.nextInt(blockTypes.size());
                    // 获取随机数，将该随机数作为下标获取消除物类型
                    blockType = blockTypes.get(randomNum);
                    // 将获取到的随机消除物显示相应图片
                    blockImage = loadImage(blockType);
                    // 检查该消除物与其之上边两格内元素是否相同，返回布尔值
                    aboveHasSameType = i > 1 && map[i - 1][j].getBlockType() == blockType && map[i - 2][j].getBlockType() == blockType;
                    // 检查该消除物与其之左边两格内元素是否相同，返回布尔值
                    leftHasSameType = j > 1 && map[i][j - 1].getBlockType() == blockType && map[i][j - 2].getBlockType() == blockType;
                    // 若布尔值有一方为true，表示上方或左边有相邻两格元素相同，重新进入循环进行随机
                } while (aboveHasSameType || leftHasSameType);
                // 初始化消除物属性
                map[i][j] = new Block(i * cols + j, i, j, blockType, blockImage);
                map[i][j].setY(Data.START_Y + i * Data.GRID);
                map[i][j].setX(Data.START_X + j * Data.GRID);
            }
        }
    }

    // 初始化菱形地图
    public static void generateLozengeMap() {
        List<Integer> blockTypes;
        // 获取消除物类型集合
        if (Data.CUSTOM == 1) {
            blockTypes = blockTypes();
        } else {
            blockTypes = setBlockTypes();
        }
        // 将集合内的数据打乱
        Collections.shuffle(blockTypes, new Random());
        // 新建随机数
        Random random = new Random();
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[0].length; j++) {
                if (Math.abs(i - rows / 2) + Math.abs(j - cols / 2) > rows / 2) {
                    // 菱形边框生成障碍物
                    map[i][j] = new Block(i * cols + j, i, j, 0,new ImageIcon("Image/zhuankuai.jpg").getImage());
                } else {
                    // 定义随机数
                    int randomNum;
                    // 定义消除物类型
                    int blockType;
                    // 定义消除物图片
                    Image blockImage;
                    // 定义向上元素是否相同
                    boolean aboveHasSameType;
                    // 定义向左元素是否相同
                    boolean leftHasSameType;
                    // do...while循环（先运行再判断进入循环）
                    do {
                        // 在类型范围进行随机数
                        randomNum = random.nextInt(blockTypes.size());
                        // 获取随机数，将该随机数作为下标获取消除物类型
                        blockType = blockTypes.get(randomNum);
                        // 将获取到的随机消除物显示相应图片
                        blockImage = loadImage(blockType);
                        // 检查该消除物与其之上边两格内元素是否相同，返回布尔值
                        aboveHasSameType = i > 1 && map[i - 1][j].getBlockType() == blockType && map[i - 2][j].getBlockType() == blockType;
                        // 检查该消除物与其之左边两格内元素是否相同，返回布尔值
                        leftHasSameType = j > 1 && map[i][j - 1].getBlockType() == blockType && map[i][j - 2].getBlockType() == blockType;
                        // 若布尔值有一方为true，表示上方或左边有相邻两格元素相同，重新进入循环进行随机
                    } while (aboveHasSameType || leftHasSameType);
                    // 初始化消除物属性
                    map[i][j] = new Block(i * cols + j, i, j, blockType, blockImage);
                }
                map[i][j].setY(Data.START_Y + i * Data.GRID);
                map[i][j].setX(Data.START_X + j * Data.GRID);
            }
        }
    }

    // 初始化心形地图
    public static void generateHeartShapedMap() {
        List<Integer> blockTypes;
        // 获取消除物类型集合
        if (Data.CUSTOM == 1) {
            blockTypes = blockTypes();
        } else {
            blockTypes = setBlockTypes();
        }
        // 将集合内的数据打乱
        Collections.shuffle(blockTypes, new Random());
        // 新建随机数
        Random random = new Random();
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[0].length; j++) {
                if (heartShape[i][j] == 1) {
                    // 定义随机数
                    int randomNum;
                    // 定义消除物类型
                    int blockType;
                    // 定义消除物图片
                    Image blockImage;
                    // 定义向上元素是否相同
                    boolean aboveHasSameType;
                    // 定义向左元素是否相同
                    boolean leftHasSameType;
                    // do...while循环（先运行再判断进入循环）
                    do {
                        // 在类型范围进行随机数
                        randomNum = random.nextInt(blockTypes.size());
                        // 获取随机数，将该随机数作为下标获取消除物类型
                        blockType = blockTypes.get(randomNum);
                        // 将获取到的随机消除物显示相应图片
                        blockImage = loadImage(blockType);
                        // 检查该消除物与其之上边两格内元素是否相同，返回布尔值
                        aboveHasSameType = i > 1 && map[i - 1][j].getBlockType() == blockType && map[i - 2][j].getBlockType() == blockType;
                        // 检查该消除物与其之左边两格内元素是否相同，返回布尔值
                        leftHasSameType = j > 1 && map[i][j - 1].getBlockType() == blockType && map[i][j - 2].getBlockType() == blockType;
                        // 若布尔值有一方为true，表示上方或左边有相邻两格元素相同，重新进入循环进行随机
                    } while (aboveHasSameType || leftHasSameType);
                    // 初始化消除物属性
                    map[i][j] = new Block(i * cols + j, i, j, blockType, blockImage);
                } else {
                    // 在心形外的位置生成障碍物
                    map[i][j] = new Block(i * cols + j, i, j, 0,new ImageIcon("Image/zhuankuai.jpg").getImage());
                }
                map[i][j].setY(Data.START_Y + i * Data.GRID);
                map[i][j].setX(Data.START_X + j * Data.GRID);
            }
        }
    }


    public static int getRows() {
        return rows;
    }

    public static int getLevel() {
        return level;
    }

    public static Block[][] getMap() {
        return map;
    }

    public static int isMapType() {
        return mapType;
    }

    public static void setMapType(int mapType) {
        Map.mapType = mapType;
    }

    public static int[][] getHeartShape() {
        return heartShape;
    }

    public static int getMaxBlockType() {
        return maxBlockType;
    }

    public static void setMaxBlockType(int maxBlockType) {
        Map.maxBlockType = maxBlockType;
    }

    public static int[][] getSaveMap() {
        return saveMap;
    }

    public static void setLevel(int level) {
        Map.level = level;
    }
}
